﻿using Infrastructure.Extension;
using JinianNet.JNTemplate;
using Medallion.Threading;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Quartz;

namespace Application.Job
{
    public class NoticeJob : IJob
    {
        private readonly JobManagerDbContext _dbContext;
        private readonly IConfiguration _config;
        private readonly IDistributedLockProvider _synchronizationProvider;
        public NoticeJob(JobManagerDbContext dbContext, IConfiguration configuration, IDistributedLockProvider synchronizationProvider)
        {
            _dbContext = dbContext;
            _config = configuration;
            _synchronizationProvider = synchronizationProvider;
        }
        //通知
        public async Task Execute(IJobExecutionContext context)
        {
            //return;
            using (this._synchronizationProvider.AcquireLock($"UserAccount{Resource.Notice}"))
            {
                var notices = await _dbContext.Notice.Where(s => s.CreateTime > DateTime.Now.AddDays(-2)).ToListAsync();
                var pendingNotices = notices.Where(s => s.NoticeStatus == NoticeStatus.Pending).ToList();
                if (pendingNotices.Has())
                {
                    var setting = await _dbContext.KeyValue.Where(s => s.Type == KeyValueType.SettingNotice).ToListAsync();
                    var noticeLimit = setting.FirstOrDefault(s => s.Key.ToLower() == Enum.GetName(SettingKey.NoticeLimit).ToLower());
                    var emailServer = setting.FirstOrDefault(s => s.Key.ToLower() == Enum.GetName(SettingKey.EmailServer).ToLower());
                    var appName = setting.FirstOrDefault(s => s.Key.ToLower() == Enum.GetName(SettingKey.AppName).ToLower());

                    if (noticeLimit == null || emailServer == null) return;

                    var template = Engine.LoadTemplate($"{AppDomain.CurrentDomain.BaseDirectory}/Data/notice.html");
                    var emailServerArr = emailServer.Value.Split("$");

                    var needNotics = new List<(string, string)>();//确定要发送的集合，用于合并发送
                    var limitNotics = new List<(string, string)>();//受限制的通知
                    //notices = _dbContext.Notice.Where(s => s.CreateTime > DateTime.Now.AddDays(-2)).ToList();
                    if (!notices.Has()) return;
                    //var pendingNotices = notices.Where(s => s.NoticeStatus == NoticeStatus.pending).ToList();
                    var sentNotices = notices.Where(s => s.NoticeStatus == NoticeStatus.Sent).ToList();

                    var noticeObjects = pendingNotices.Select(s => s.NoticeObject).Where(s => s.Has()).Distinct().ToList();

                    #region 限制策略
                    var limitOption = noticeLimit;
                    var limits = limitOption.Value.Split("-").Select(s => Convert.ToInt32(s)).ToList();
                    var minute = limits[0];
                    var hour = limits[1];
                    var day = limits[2];
                    foreach (var noticeObject in noticeObjects)
                    {
                        var thisSentNotices = sentNotices.Where(s => s.NoticeObject == noticeObject).ToList();

                        if (thisSentNotices.Count(s => s.CreateTime > DateTime.Now.AddDays(-1)) >= day)
                        {
                            limitNotics.Add((noticeObject, $"一天最多{day}条"));
                            continue;
                        }
                        if (thisSentNotices.Count(s => s.CreateTime > DateTime.Now.AddHours(-1)) >= hour)
                        {
                            limitNotics.Add((noticeObject, $"一小时最多{hour}条"));
                            continue;
                        }
                        if (thisSentNotices.Count(s => s.CreateTime > DateTime.Now.AddMinutes(-1)) >= minute)
                        {
                            limitNotics.Add((noticeObject, $"一分钟最多{minute}条"));
                            continue;
                        }
                        #region 临近阈值
                        var nearThreshold = "";
                        var test = thisSentNotices.Count(s => s.CreateTime > DateTime.Now.AddDays(-1));
                        if (thisSentNotices.Count(s => s.CreateTime > DateTime.Now.AddDays(-1)) == day - 1)
                        {
                            nearThreshold = $"发送条数阈值提醒：一天最多{day}条;";
                        }
                        if (thisSentNotices.Count(s => s.CreateTime > DateTime.Now.AddHours(-1)) == hour - 1)
                        {
                            nearThreshold += $"发送条数阈值提醒：一小时最多{hour}条;";
                        }
                        if (thisSentNotices.Count(s => s.CreateTime > DateTime.Now.AddMinutes(-1)) == minute - 1)
                        {
                            nearThreshold += $"发送条数阈值提醒：一分钟最多{minute}条;";
                        }
                        #endregion

                        //加入发送对象集合
                        needNotics.Add((noticeObject, nearThreshold));
                    }
                    #endregion

                    //通知-可用Task.Run
                    var maxItemCount = 100;//每封邮件最大显示100项，避免过多无法渲染
                    foreach (var objectItem in needNotics.Distinct())
                    {
                        var items = pendingNotices.Where(s => s.NoticeObject == objectItem.Item1).ToList();
                        if (!items.Has()) continue;
                        var datas = new List<NoticeHtmlTemplateData> { };
                        foreach (var notice in items)
                        {
                            datas.Add(new NoticeHtmlTemplateData
                            {
                                Title = notice.Title,
                                Status = notice.IsBusinessSuccess ? "正常" : "异常",
                                BackColor = notice.IsBusinessSuccess ? "#ebffe1" : "#fff4e4",
                                ExecutionTime = notice.CreateTime.DateTime(),
                                Details = notice.Content,
                                Source = appName?.Value,
                                Note = objectItem.Item2
                            });
                        }
                        #region 限制item count
                        if (datas.Count > maxItemCount)
                        {
                            var count = datas.Count;
                            datas = datas.GetRange(0, maxItemCount);
                            datas.Add(new NoticeHtmlTemplateData
                            {
                                Status = $"--",
                                Title = $"已超出{maxItemCount}项，更多请查看系统",
                                Details = $"更多的{count - maxItemCount}项，请查看系统",
                                ExecutionTime = $"--",
                                Source = appName?.Value,
                            });
                        }
                        #endregion
                        template.Set("datas", datas);
                        var html = template.Render();
                        try
                        {
                            var sysEmail = new SysEmail(emailServerArr[0], Convert.ToInt32(emailServerArr[1]), emailServerArr[2], emailServerArr[3]);
                            var isSuccess = sysEmail.Send($"检测通知({datas.Count}条)", html, objectItem.Item1, IsBodyHtml: true).Result;
                            items.ForEach(s => s.SentResult = isSuccess ? "发送成功" : "发送失败");
                        }
                        catch (Exception e)
                        {
                            items.ForEach(s => s.SentResult = $"发送失败：{e.Combine()}");
                        }
                        foreach (var notice in items)
                        {
                            notice.NoticeStatus = NoticeStatus.Sent;
                            notice.SentTime = DateTime.Now;
                        }
                    }
                    foreach (var item in limitNotics)
                    {
                        var items = pendingNotices.Where(s => s.NoticeObject == item.Item1).ToList();
                        foreach (var notice in items)
                        {
                            notice.NoticeStatus = NoticeStatus.NotSent;
                            notice.SentTime = DateTime.Now;
                            notice.SentResult = $"未发送(达到阈值:{item.Item2})";
                        }
                    }

                    _dbContext.SaveChanges();
                }
            }
            return;
        }
    }

    public class NoticeHtmlTemplateData
    {
        public string Title { get; set; }
        public string Status { get; set; }
        public string BackColor { get; set; }
        public string ExecutionTime { get; set; }
        public string Details { get; set; }
        public string Source { get; set; }
        public string Note { get; set; }
    }

    public enum Status
    {
        success = 0,//绿色#ebffe1
        info = 1,//灰色#80808012
        warning = 2,//橙色#fff4e4
        danger = 3,//红色#ffe1e1
    }
}
